﻿
/**
	自定义OSG 文件读写器
**/

#include <windows.h>
#include <iostream>
#include <sstream>

#include <osg/Image>
#include <osg/Group>
#include <osg/Notify>
#include <osg/Version>
#include <osg/Geode>
#include <osg/Shape>
#include <osg/ShapeDrawable>

#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/fstream>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>

using namespace osg;
using namespace osgDB;

class FSReaderWriter : public ReaderWriter
{
public:

	mutable OpenThreads::Mutex _mutex;
	mutable bool _wrappersLoaded;

	FSReaderWriter()
	{
		supportsExtension("fs", "FreeSouth 's format");
	}

	virtual const char* className() const { return "FSReaderWriter"; }

	bool loadWrappers() const
	{
#ifndef OSG_LIBRARY_STATIC
		if (_wrappersLoaded) return true;

		OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
		if (_wrappersLoaded) return true;

		std::string filename = osgDB::Registry::instance()->createLibraryNameForExtension("fsreadwrite_osg");
		if (osgDB::Registry::instance()->loadLibrary(filename) == osgDB::Registry::LOADED)
		{
			OSG_INFO << "FSReaderWriter wrappers loaded OK" << std::endl;
			_wrappersLoaded = true;
			return true;
		}
		else
		{
			OSG_NOTICE << "FSReaderWriter wrappers failed to load" << std::endl;
			_wrappersLoaded = true;
			return false;
		}
#else
		return true;
#endif
	}

	virtual ReadResult readNode(const std::string& file, const Options* opt) const
	{
		std::string ext = osgDB::getLowerCaseFileExtension(file);

		if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

		std::string fileName = osgDB::findDataFile(file, opt);
		if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

		osgDB::ifstream fin(fileName.c_str());  // 非常耗时，相当于fopen()函数
		if (!fin)
		{
			std::cerr << "Failed to open file: " << fileName << std::endl;
			return ReadResult::FILE_NOT_FOUND;
		}
		return readNode(fin, opt);

	}

	virtual ReadResult readNode(std::istream& fin, const Options* options) const
	{
		Input fr;
		fr.attach(&fin);

		osg::ref_ptr<osg::Geode> gnode = new osg::Geode;

		osg::Vec3 center;
		float radius;

		// load all nodes in file, placing them in a group.
		while (!fr.eof())
		{
			// 匹配文件中中心点，跟半径
			if (fr.matchSequence("%f%f%f%f"))
			{
				fr.readSequence(center);
				fr.readSequence(radius);
				std::cout << "Center is:" << center.x() << " " << center.y() << " " << center.z() << std::endl;
				std::cout << "Radius:" << radius << std::endl;
				gnode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(center, radius)));
			}
			else {
				std::cout << "fr is NULL" << std::endl;
				++fr;
			}
		}
		return gnode;
	}


	virtual WriteResult writeNode(const Node& node, const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
	{
		std::string ext = getFileExtension(fileName);
		if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
		int numDrawables = node.asGeode()->getNumDrawables();
		osg::Vec3 vc;

		osgDB::Output fout(fileName.c_str());
		if (fout)
		{

			for (int i = 0; i < numDrawables; i++)
			{
				const osg::Shape* shape = node.asGeode()->getDrawable(i)->getShape();
				vc = dynamic_cast<const osg::Sphere*>(shape)->getCenter();

				fout.setOptions(options);

				fout.imbue(std::locale::classic());

				fout << vc.x() << " " << vc.y() << " " << vc.z() << " " << dynamic_cast<const osg::Sphere*>(shape)->getRadius() << std::endl;
				//fout.writeObject(node);
				
			}

			fout.close();
			return WriteResult::FILE_SAVED;
		}
		return WriteResult("Unable to open file for output");
	}

};

// now register with Registry to instantiate the above
// reader/writer.
REGISTER_OSGPLUGIN(fs, FSReaderWriter)